#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "PlayWidget.h"
#include "stateMonitorWidget.h"
#include "waveWidget.h"
#include "ConfigImport.h"
#include "EmoRecBase.h"
#include "dialogMessageBox.h"

#include "BackgroundProgram.h"

#include <QMessageBox>
#include <iostream>
#include <QDebug>
#include <QCloseEvent>
#include <QScreen>

#include <QFileDialog>
// 设备不在线时，DEVICE_CONNECT清零
#define DEVICE_CONNECT  1
// 是否启动仿真设备
#define SIMULATION      0
#define DEBUG

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
    , eegDataRelay(new EEGDataRelay(ConfigImport::getInstance()))

    , program(ConfigImport::getInstance())
{
    // 参数初始化
    win_open_flag = WINID::Mainwindow;
    // eeg_dev1 = nullptr;
    // sim_eeg_dev = nullptr;
    // stateMonitorWidget_ui = nullptr;
    // waveWidget_ui = nullptr;
    // playwin = nullptr;

    ui->setupUi(this);
    // // 线程池初始化，设置最大线程池数
    // QThreadPool::globalInstance()->setMaxThreadCount(4);

    QButtonGroup *workMode_group = new QButtonGroup;
    workMode_group->addButton(ui->rbtn_train,0);
    workMode_group->addButton(ui->rbtn_test,1);
    ui->rbtn_train->setChecked(true);

    // 初始化脑电采集设备，并且绑定信号发送函数和槽函数
    program.collectingDeviceInit();

    // 状态显示窗口
    stateMonitorWidget_ui = new StateMonitorWidget(program.getElectrodeNameMap());
    // 脱落检测窗口
    dropoutDectectionWidget_ui = new DropoutDetectionWidget();
    // 波形显示窗口
    waveWidget_ui = new WaveWidget();
    // 神经调控窗口
    regulationWidget_ui = new RegulationWidget();

    
    // 情绪识别内核
    // EmoRecBase *EmoRecBase = new EmoRecBase(*(ConfigImport::getInstance()));
    emoRecogCore = new EmoRecogCore(ConfigImport::getInstance());
    // connect(&timer_test, SIGNAL(timeout()), emoRecogCore, SLOT(run()));
    // timer_test.start(100);

    // 视频播放窗口
    playwin = new PlayWidget();
    /* 被监控对象为MainWindow窗口，为其注册事件过滤器 */
    this->installEventFilter(this);
    
    // 槽函数连接
    // 绑定进程退出槽函数
    // connect(mpvProcess, SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(video_shutDown(int,QProcess::ExitStatus)));

    // 窗口关闭
    connect(stateMonitorWidget_ui, SIGNAL(widgetClose(uint8_t)), this, SLOT(event_widgetClose(uint8_t)));
    connect(waveWidget_ui, SIGNAL(widgetClose(uint8_t)), this, SLOT(event_widgetClose(uint8_t)));
    connect(dropoutDectectionWidget_ui, SIGNAL(widgetClose(uint8_t)), this, SLOT(event_widgetClose(uint8_t)));
    
    // 波形显示
    connect(&program, 
            &BackgroundProgram::send_singleData, 
            stateMonitorWidget_ui, 
            static_cast<void (StateMonitorWidget::*)(const GenEEGData&)>
                        (&StateMonitorWidget::plotDataUpdate));

    // 数据打标
    connect(playwin, &PlayWidget::sendDataLabel, &program, &BackgroundProgram::slt_setDataLabel);
    
    // // 情绪解码
    // connect(&program, 
    //         &BackgroundProgram::send_oneTrialData,
    //         emoRecogCore,
    //         QOverload<const GenEEGData &>::of(&EmoRecogCore::receiveData)
    // );
    // 解码结果
    connect(emoRecogCore, 
            &EmoRecogCore::send_predictResult, 
            stateMonitorWidget_ui, 
            static_cast<void (StateMonitorWidget::*)(int)>(&StateMonitorWidget::setCurrent_emotion));

    connect(&program, 
            &BackgroundProgram::send_oneTrialData,
            stateMonitorWidget_ui,
            &StateMonitorWidget::networkPlot
    );

    
    // 播放视频标签
    connect(playwin, static_cast<void (PlayWidget::*)(EmotionInterface::EmoMode)>(&PlayWidget::sendVideoLabel),
            stateMonitorWidget_ui, static_cast<void (StateMonitorWidget::*)(EmotionInterface::EmoMode)>(&StateMonitorWidget::setVideo_emotion));
    connect(playwin, static_cast<void (PlayWidget::*)(EmotionInterface::EmoMode)>(&PlayWidget::sendVideoLabel),
            emoRecogCore, static_cast<void (EmoRecogCore::*)(EmotionInterface::EmoMode)>(&EmoRecogCore::slt_receivePredictVideoLabel));
    
    // 播放视频
    connect(&delay_playVideoTimer, SIGNAL(timeout()), playwin, SLOT(work()));

    // 脑网络
    connect(&program, &BackgroundProgram::send_network, stateMonitorWidget_ui, &StateMonitorWidget::receive_network);
    connect(&timer_simNetwork, SIGNAL(timeout()), stateMonitorWidget_ui, SLOT(networkPlot()));
    
    
    // if(1){
    if(ConfigImport::getInstance()->use_simulationDev()){
        // 演示模式
        // connect(&timer_simNetwork, SIGNAL(timeout()), stateMonitorWidget_ui, SLOT(networkPlot_test()));// 脑网络
    }
    
    // 开始信号
    // connect(this, static_cast<void (MainWindow::*)(EmoRecogCore::WorkingMode)>(&MainWindow::setEmoRecMode),
    //         emoRecogCore, static_cast<void (EmoRecogCore::*)(EmoRecogCore::WorkingMode)>(&EmoRecogCore::setWorkingMode));

    // this->setWindowTitle(QString::fromUtf8("便携式情绪在线监测与闭环调控系统"));

}

/**********************************
 * 函数名：plotDataUpdate
 * 功能：将放大器数据更新到界面显示缓冲区
 * 输入：无
 * 输出：无
 * 备注：slots
**********************************/
// void MainWindow::plotDataUpdate(){stateMonitorWidget_ui->plotDataUpdate(program.get_eegData());}
bool MainWindow::eventFilter(QObject *obj, QEvent *ev)
{
    /*判断发生事件的是否为主窗口*/
    if(obj==this) {
        /*判断事件的类型是否为关闭事件*/
        if (ev->type() == QEvent::Close){ 
            {
                // 清除采集线程
                program.stopCollecting();
                // 保存剩下的数据
                // program.saveEEGData("../Data/EEGData.dat", program.org_eegData, true);
                program.org_eegData.saveData("../Data/EEGData.dat", true);
                // GenEEGData dataFromFile;
                // dataFromFile.loadData("../bin/EEGData.dat");
                // dataFromFile.saveData("../bin/save.dat",true);
            }
            qApp->quit();//主窗口关闭事件,程序退出,其他窗口将被关闭
            std::cout << "MainWindow is closed" << std::endl;
            return true; //返回true代表事件已被处理不需要向下传递，返回false代表事件未被处理需要向下传递由别的组件处理
        }
    }
    /*不是我们关心的事件，交由QMainWindow的事件过滤器处理*/
    return QMainWindow::eventFilter(obj, ev);
}

MainWindow::~MainWindow()
{
    
    // delete mpvProcess;
    delete eegDataRelay;
    delete stateMonitorWidget_ui;
    delete dropoutDectectionWidget_ui;
    delete waveWidget_ui;
    delete regulationWidget_ui;
    delete playwin;
    
    delete ui;
    // std::cout << "~MainWindow" << std::endl;
}

void MainWindow::noiseLabel(){
    QEventLoop loop;//定义一个新的事件循环
    for(int i=0; i<2; ++i){
        QTimer::singleShot(100, &loop, SLOT(quit()));//创建单次定时器，槽函数为事件循环的退出函数
        loop.exec();//事件循环开始执行，程序会卡在这里，直到定时时间到，本循环被退出
        stateMonitorWidget_ui->setCurrent_emotion(static_cast<EmotionInterface::EmoMode>(label_group[i%3]));
        // stateMonitorWidget_ui->set_emoGIF();
    }

    for(int i=0; i<3; ++i){
        QTimer::singleShot(200, &loop, SLOT(quit()));//创建单次定时器，槽函数为事件循环的退出函数
        loop.exec();//事件循环开始执行，程序会卡在这里，直到定时时间到，本循环被退出
        stateMonitorWidget_ui->setCurrent_emotion(static_cast<EmotionInterface::EmoMode>(label_group[i%3]));
        // stateMonitorWidget_ui->set_emoGIF();
    }

    for(int i=0; i<3; ++i){
        QTimer::singleShot(400, &loop, SLOT(quit()));//创建单次定时器，槽函数为事件循环的退出函数
        loop.exec();//事件循环开始执行，程序会卡在这里，直到定时时间到，本循环被退出
        stateMonitorWidget_ui->setCurrent_emotion(static_cast<EmotionInterface::EmoMode>(label_group[i%3]));
        // stateMonitorWidget_ui->set_emoGIF();
    }
}

void MainWindow::test_showEmoLabel(){
    static int flag = 0;
    static int flag_noise = 0;
    static EmotionInterface::EmoMode pre_currentEmo = EmotionInterface::EmoMode::Free;
    EmotionInterface::EmoMode currentEmo = stateMonitorWidget_ui->getVideoEmotion();
    if(!flag){
        stateMonitorWidget_ui->setGraph_visible(1,true);
        flag = 1;
        return;
    }
    if(!flag_noise){
        flag_noise = 1;
        // 先显示标签
        noiseLabel();
    }

    // 根据视频标签显示情绪label
    QEventLoop loop;//定义一个新的事件循环
    QTimer::singleShot(6500, &loop, SLOT(quit()));//创建单次定时器，槽函数为事件循环的退出函数
    loop.exec();//事件循环开始执行，程序会卡在这里，直到定时时间到，本循环被退出

    // 发生改变再画图
    if(pre_currentEmo == currentEmo){return;}
    stateMonitorWidget_ui->setCurrent_emotion(currentEmo);
    stateMonitorWidget_ui->set_emoGIF();
    pre_currentEmo = currentEmo;
    // delay_playVideoTimer.stop();
}

void MainWindow::on_btn_start_clicked(bool checked)
{
    if(win_open_flag & WINID::Video_Playing){
        std::cout << "Video is allready playing!" << std::endl;
    }
    else{
        // 非演示模式直接不进行视频播放
        if(0){
        // if(ConfigImport::getInstance()->use_simulationDev() == false){
            // 配置弹窗样式表
            QString styleSheet = "QLabel { font-size: 16pt; text-align: center;}"  // 设置消息文本的字体大小
                                "QPushButton { font-size: 14pt; }"; // 设置按钮的字体大小
            // 显示信息消息框
            QMessageBox msgBox(this);
            msgBox.setStyleSheet(styleSheet);
            msgBox.setWindowTitle(QObject::tr("error"));
            msgBox.setText(QObject::tr("        \n请正确佩戴脑电帽..\n"));
            msgBox.setIconPixmap(QIcon(":/pic/pic/circle_red.png").pixmap(48, 48));
            msgBox.setStandardButtons(QMessageBox::Ok);
            msgBox.setDefaultButton(QMessageBox::Ok);
            msgBox.resize(600, 400); // 尝试设置特定大小
            msgBox.exec();

            return;
        }

        win_open_flag |= WINID::Video_Playing;

        // 判断现在是训练还是测试
        bool train_mode = ui->rbtn_train->isChecked();
        // 训练模式不显示表情和预测状态
        if(!train_mode){
            program.fileNames = QFileDialog::getOpenFileNames(this, "选择视频文件", "../AllVideo/", "视频文件 (*.mp4 *.avi *.mkv)");
            playwin->set_play_mode(1);
            playwin->setVideoList(program.fileNames);
            playwin->set_Video_flag(true);
            delay_playVideoTimer.start(500);
            stateMonitorWidget_ui->setGraph_visible(1,true);
            stateMonitorWidget_ui->set_emoGIF();
            stateMonitorWidget_ui->emoLabel_startPlot();

            emoRecogCore->setWorkingMode(EmoRecogCore::Predict);// 识别模块进入测试模式
            // 预测模式的数据接收通过信号槽来接收网络数据
            connect(&program, &BackgroundProgram::send_network, emoRecogCore, &EmoRecogCore::slt_receivePredictData);

            connect(playwin, &PlayWidget::videoPlayer_shutDown, this, [=](){
                playwin->set_play_mode(-1);
                delay_playVideoTimer.stop();
                stateMonitorWidget_ui->emoLabel_stopPlot();
                // stateMonitorWidget_ui->hideEmoGIF();
                disconnect(&program, &BackgroundProgram::send_network, emoRecogCore, &EmoRecogCore::slt_receivePredictData);
                emoRecogCore->setWorkingMode(EmoRecogCore::Free);// 识别模块进入空闲模式

                // 输出准确率
                emoRecogCore->showAcc();


                playwin->showWords("任务结束");
                win_open_flag &= ~WINID::Video_Playing;
                playwin->disconnect(SIGNAL(videoPlayer_shutDown()));

            });
        }
        else{
            printf("train\n");
            program.fileNames = QFileDialog::getOpenFileNames(this, "选择构建模型的视频文件", "../AllVideo/", "视频文件 (*.mp4 *.avi *.mkv)");
            playwin->set_play_mode(0);
            playwin->setVideoList(program.fileNames);

            connect(playwin, &PlayWidget::videoPlayer_shutDown, this, [=](){
                playwin->set_play_mode(-1);
                delay_playVideoTimer.stop();
                stateMonitorWidget_ui->emoLabel_stopPlot();
                program.org_eegData.saveData("../Data/EEGData.dat", true);
                std::vector<int> label;
                emoRecogCore->setWorkingMode(EmoRecogCore::Train);
                emoRecogCore->receiveData(program.cropValidData(label));
                program.org_eegData.clear();// 历史数据存进文件并清空缓存，此时pointIndex没有清空，会接着记录点数
                std::cout << "sum label len:" << emoRecogCore->insertLabel(label) << std::endl;
                emoRecogCore->run();
                // 配置弹窗样式表
                QString styleSheet = "QLabel { font-size: 16pt; text-align: center;}"  // 设置消息文本的字体大小
                                    "QPushButton { font-size: 14pt; }"; // 设置按钮的字体大小
                // 显示信息消息框
                QMessageBox msgBox(this);
                msgBox.setStyleSheet(styleSheet);
                msgBox.setWindowTitle(QObject::tr("finish"));
                msgBox.setText(QObject::tr("        训练结束\n情感模型构建完成!"));
                msgBox.setIconPixmap(QIcon(":/pic/pic/correct.png").pixmap(48, 48));
                msgBox.setStandardButtons(QMessageBox::Ok);
                msgBox.setDefaultButton(QMessageBox::Ok);
                msgBox.resize(600, 400); // 尝试设置特定大小
                msgBox.exec();

                win_open_flag &= ~WINID::Video_Playing;
                playwin->disconnect(SIGNAL(videoPlayer_shutDown()));
            });

            delay_playVideoTimer.start(500);
            playwin->set_Video_flag(true);
            stateMonitorWidget_ui->emoLabel_startPlot();

        }
    }
}

void MainWindow::on_btn_stateMonitor_clicked(bool checked){
    if(win_open_flag & WINID::StateMonitorWidget){
        std::cout << "StateMonitor Window is allready opened!" << std::endl;
    }
    else{
        win_open_flag |= WINID::StateMonitorWidget;
        stateMonitorWidget_ui->setWindowTitle("stateMonitor");
        stateMonitorWidget_ui->show();
    }
}

void MainWindow::on_btn_wave_clicked(bool checked){
    if(win_open_flag & WINID::WaveWidget){
        std::cout << "Wave Window is allready opened!" << std::endl;
    }
    else{
        win_open_flag |= WINID::WaveWidget;
        waveWidget_ui->setWindowTitle("waveWidget");
        waveWidget_ui->show();
    }

}
void MainWindow::on_btn_dropoutDetection_clicked(bool checked){
    if(win_open_flag & WINID::DropoutDetectionWidget){
        std::cout << "DropoutDetection Window is allready opened!" << std::endl;
    }
    else{
        win_open_flag |= WINID::DropoutDetectionWidget;
        dropoutDectectionWidget_ui->show();
    }

}
void MainWindow::on_btn_eegCollect_clicked(bool checked){
    // 停止采集
    if(win_open_flag & WINID::EEGCollectWidget){
        win_open_flag &= ~WINID::EEGCollectWidget;
        ui->btn_eegCollect->setText("开始采集");
        program.stopCollecting();
        timer_plotAddData.stop();
        timer_simNetwork.stop();
        timer_Network.stop();
    }
    // 开始采集
    else{
        win_open_flag |= WINID::EEGCollectWidget;
        ui->btn_eegCollect->setText("停止采集");
        program.collectingData();
        timer_plotAddData.start(5);
        timer_simNetwork.start(1000);
        timer_Network.start(1000);
    }
}
void MainWindow::on_btn_regulation_clicked(bool checked){
    if(win_open_flag & WINID::Regulation){
        // win_open_flag &= ~WINID::Regulation;
        std::cout << "Regulation Windows is allready opened!" << std::endl;
    }
    else{











        // 演示模式直接不进行视频播放
        if(0){
        // if(ConfigImport::getInstance()->use_simulationDev() == false){
            // 配置弹窗样式表
            QString styleSheet = "QLabel { font-size: 16pt; text-align: center;}"  // 设置消息文本的字体大小
                                "QPushButton { font-size: 14pt; }"; // 设置按钮的字体大小
            // 显示信息消息框
            QMessageBox msgBox(this);
            msgBox.setStyleSheet(styleSheet);
            msgBox.setWindowTitle(QObject::tr("error"));
            msgBox.setText(QObject::tr("        \n请正确佩戴脑电帽..\n"));
            msgBox.setIconPixmap(QIcon(":/pic/pic/circle_red.png").pixmap(48, 48));
            msgBox.setStandardButtons(QMessageBox::Ok);
            msgBox.setDefaultButton(QMessageBox::Ok);
            msgBox.resize(600, 400); // 尝试设置特定大小
            msgBox.exec();

            return;
        }
        
        win_open_flag |= WINID::Regulation;
        connect(regulationWidget_ui, &RegulationWidget::showVideo,
                playwin, &PlayWidget::playVideoFromFile);

        connect(regulationWidget_ui, SIGNAL(widgetClose(uint8_t)), this, SLOT(event_widgetClose(uint8_t)));
        
        stateMonitorWidget_ui->setCurrent_emotion(EmotionInterface::EmoMode::Neutral);
        stateMonitorWidget_ui->setGraph_visible(1,true);
        stateMonitorWidget_ui->emoLabel_startPlot();
        stateMonitorWidget_ui->set_emoGIF();

        regulationWidget_ui->show();
        regulationWidget_ui->delay_time.start(4000);

        QEventLoop loop;//定义一个新的事件循环
        QTimer::singleShot(3500, &loop, SLOT(quit()));//创建单次定时器，槽函数为事件循环的退出函数
        loop.exec();//事件循环开始执行，程序会卡在这里，直到定时时间到，本循环被退出
        stateMonitorWidget_ui->setCurrent_emotion(EmotionInterface::EmoMode::Negative);
        stateMonitorWidget_ui->set_emoGIF();

        QTimer::singleShot(3500+8000, &loop, SLOT(quit()));//创建单次定时器，槽函数为事件循环的退出函数
        loop.exec();//事件循环开始执行，程序会卡在这里，直到定时时间到，本循环被退出
        stateMonitorWidget_ui->setCurrent_emotion(EmotionInterface::EmoMode::Positive);
        stateMonitorWidget_ui->set_emoGIF();
        regulationWidget_ui->happyGIF();
    }
}

void MainWindow::event_widgetClose(uint8_t winID){
    switch (winID)
    {
        case WINID::StateMonitorWidget:
        win_open_flag &= ~WINID::StateMonitorWidget;
        break;

        case WINID::DropoutDetectionWidget:
        win_open_flag &= ~WINID::DropoutDetectionWidget;
        break;

        case WINID::WaveWidget:
        win_open_flag &= ~WINID::WaveWidget;
        break;

        case WINID::Regulation:
        win_open_flag &= ~WINID::Regulation;
        break;
    
    default:
        break;
    }
}


